package com.atguigu.lease.web.admin.service.impl;

import com.atguigu.lease.common.constant.RedisConstant;
import com.atguigu.lease.common.exception.LeaseException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.common.utils.JwtUtil;
import com.atguigu.lease.model.entity.SystemUser;
import com.atguigu.lease.model.enums.BaseStatus;
import com.atguigu.lease.web.admin.service.LoginService;
import com.atguigu.lease.web.admin.service.SystemUserService;
import com.atguigu.lease.web.admin.vo.login.CaptchaVo;
import com.atguigu.lease.web.admin.vo.login.LoginVo;
import com.atguigu.lease.web.admin.vo.system.user.SystemUserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wf.captcha.SpecCaptcha;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * Package: com.atguigu.lease.web.admin.service.impl
 *
 * @Description:
 * @Author xiongkunYang
 * @Create 2025/4/28 10:22
 */
@Service
public class LoginServiceImpl implements LoginService {
    private final StringRedisTemplate redisTemplate;
    private final SystemUserService systemUserService;

    public LoginServiceImpl(StringRedisTemplate redisTemplate, SystemUserService systemUserService) {
        this.redisTemplate = redisTemplate;
        this.systemUserService = systemUserService;
    }


    /**
     * 获取验证码信息。
     * 该方法生成一个验证码图片及其对应的唯一标识符，并将验证码文本存储到 Redis 中，
     * 同时返回包含验证码图片 Base64 编码和唯一标识符的 CaptchaVo 对象。
     *
     * @return CaptchaVo 包含验证码图片的 Base64 编码和唯一标识符的对象。
     * - base64: 验证码图片的 Base64 编码字符串。
     * - key: 验证码在 Redis 中存储的唯一标识符。
     */
    @Override
    public CaptchaVo getCaptcha() {
        // 创建一个 SpecCaptcha 对象，用于生成验证码图片和文本。
        SpecCaptcha specCaptcha = new SpecCaptcha();

        // 获取验证码文本并转换为小写，便于后续验证。
        String code = specCaptcha.text().toLowerCase();

        // 生成唯一的 Redis 键，用于存储验证码文本。
        String key = RedisConstant.ADMIN_LOGIN_PREFIX + UUID.randomUUID();

        // 将验证码文本存储到 Redis 中，并设置过期时间。
        this.redisTemplate.opsForValue().set(key, code, RedisConstant.ADMIN_LOGIN_CAPTCHA_TTL_SEC, TimeUnit.SECONDS);

        // 返回包含验证码图片 Base64 编码和唯一标识符的 CaptchaVo 对象。
        return new CaptchaVo(specCaptcha.toBase64(), key);
    }

    /**
     * 用户登录方法
     *
     * @param loginVo 登录视图对象，包含用户输入的用户名、密码和验证码
     * @return 登录成功后返回用户令牌（Token）
     * @throws LeaseException 当验证码错误、过期，用户不存在，用户被禁用或密码错误时抛出异常
     */
    @Override
    public String login(LoginVo loginVo) {
        String username = loginVo.getUsername();
        String password = loginVo.getPassword();
        String captchaKey = loginVo.getCaptchaKey();
        String captchaCode = loginVo.getCaptchaCode();

        // 校验用户名是否为空
        if (!StringUtils.hasText(username)) {
            throw new LeaseException(ResultCodeEnum.ADMIN_ACCOUNT_ERROR);
        }

        // 校验密码是否为空
        if (!StringUtils.hasText(password)) {
            throw new LeaseException(ResultCodeEnum.ADMIN_ACCOUNT_ERROR);
        }

        // 校验验证码Key是否为空
        if (!StringUtils.hasText(captchaKey)) {
            throw new LeaseException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_NOT_FOUND);
        }

        // 校验验证码内容是否为空
        if (!StringUtils.hasText(captchaCode)) {
            throw new LeaseException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_NOT_FOUND);
        }

        // 从Redis中获取存储的验证码
        String redisCode = this.redisTemplate.opsForValue().get(captchaKey);

        // 验证码不存在时，抛出异常提示用户验证码已过期
        if (redisCode == null) {
            throw new LeaseException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_EXPIRED);
        }

        // 验证码不匹配时，抛出异常提示用户验证码错误
        if (!redisCode.equalsIgnoreCase(captchaCode)) {
            throw new LeaseException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_ERROR);
        }

        // 根据用户名查询系统用户信息
        SystemUser systemUser = this.systemUserService
                .getOne(new LambdaQueryWrapper<SystemUser>()
                        .eq(SystemUser::getUsername, username));

        // 用户不存在时，抛出异常提示用户
        if (systemUser == null) {
            throw new LeaseException(ResultCodeEnum.ADMIN_ACCOUNT_NOT_EXIST_ERROR);
        }

        // 用户被禁用时，抛出异常提示用户
        if (systemUser.getStatus() == BaseStatus.DISABLE) {
            throw new LeaseException(ResultCodeEnum.ADMIN_ACCOUNT_DISABLED_ERROR);
        }

        // 密码不匹配时，抛出异常提示用户
        if (!systemUser.getPassword().equals(DigestUtils.md5Hex(password))) {
            throw new LeaseException(ResultCodeEnum.ADMIN_ACCOUNT_ERROR);
        }

        // 登录成功，生成并返回用户令牌（Token）
        return JwtUtil.createToken(systemUser.getId(), systemUser.getUsername());
    }


    @Override
    public SystemUserInfoVo getSystemUserInfoByUserId(Long userId) {
        SystemUser systemUser = this.systemUserService.getById(userId);
        return new SystemUserInfoVo(systemUser.getName(), systemUser.getAvatarUrl());
    }

}